package com.dayu.tcp.service.status;

import com.dayu.tcp.common.Platform;
import com.dayu.tcp.common.util.StrUtil;
import com.dayu.tcp.logging.Log;
import com.dayu.tcp.logging.LogFactory;
import com.dayu.tcp.service.BasicThreadFactory;
import com.dayu.tcp.service.server.Server;
import com.dayu.tcp.service.server.ServerDispatchHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

import java.net.InetSocketAddress;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author yehangtech
 * @date 2025/4/6 19:19
 * @description 状态服务器
 */
public class StatusServer extends Server {

    private static final Log log = LogFactory.getLog(StatusServer.class);

    public StatusServer() {
    }

    @Override
    protected void init() {
        openExecutor = false;
        openCount = false;
        super.init();
        this.addSharableChannelHandler("StringDecoder", new StringDecoder());
        this.addSharableChannelHandler("StringEncoder", new StringEncoder());
        this.addEventListener(new StatusMessageEventListener());
    }

    @Override
    public ChannelFuture bind() {
        init();
        NioEventLoopGroup boss = new NioEventLoopGroup(1,
                new BasicThreadFactory.Builder().namingPattern("StatusServer-BOSS-%d").daemon(true).build());
        NioEventLoopGroup worker = new NioEventLoopGroup(1,
                new BasicThreadFactory.Builder().namingPattern("StatusServer-WORKER-%d").daemon(true).build());
        serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(boss, worker)
                .childOption(ChannelOption.SO_KEEPALIVE, super.keepAlive)
                .childOption(ChannelOption.TCP_NODELAY, super.tcpNoDelay)
                .channel(Platform.useEpoll() ? EpollServerSocketChannel.class : NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) {
                        ChannelPipeline pipeline = socketChannel.pipeline();
                        pipeline.addLast("frameDecoder", new DelimiterBasedFrameDecoder(1024, Delimiters.lineDelimiter()));
                        //注册各种自定义Handler
                        LinkedHashMap<String, ChannelHandler> channelHandlerMap = getChannelHandlerMap();
                        for (Map.Entry<String, ChannelHandler> entry : channelHandlerMap.entrySet()) {
                            pipeline.addLast(entry.getKey(), entry.getValue());
                        }
                        // 注册事件分发器
                        pipeline.addLast("StatusServerDispatchHandler", new ServerDispatchHandler(eventDispatcher));
                    }
                });
        final InetSocketAddress socketAddress;
        if (StrUtil.isBlank(ip)) {
            socketAddress = new InetSocketAddress(port);
        } else {
            socketAddress = new InetSocketAddress(ip, port);
        }

        ChannelFuture future = serverBootstrap.bind(socketAddress);
        //1：服务端与客户端建立链接后 boss线程会调用回调接口。第一个注册的是大禹-TCP 自定义的回调接口
        this.addFutureEventListener((ChannelFutureListener) ch -> {
            if (ch.isSuccess()) {
                log.info("StatusServer started, listening on '" + socketAddress + "'");
            } else {
                log.error("Failed to start StatusServer '" + socketAddress + "', caused by: ", ch.cause());
            }
        });
        this.futureEventListenerList.forEach(future::addListener);
        return future;
    }
}
